<?php
/**
 * 框架系统公共函数库
 */

/**
 * html特殊字符转码
 * @param mixed $var
 * @return mixed
 */
function htmlEscape($var) {
    if(is_array($var)) {
        return array_map('htmlEscape', $var);
    } else {
        return htmlspecialchars($var, ENT_QUOTES);
    }
}

/**
 * URL重定向
 * @param string $url 重定向的URL地址 (同时兼容动态URL和静态URL：index.php?app=xxx 和 /xxx/xxx/)
 * @param integer $time 重定向的等待时间（秒）
 * @param string $msg 重定向前的提示信息
 * @return void
 */
function redirect($url, $time=0, $msg='') {
    //多行URL地址支持
    $url = str_replace(array("\n", "\r"), '', $url);
    $url = Router::encodeUrl($url);
    if(empty($msg))
        $msg = "系统将在{$time}秒之后自动跳转到{$url}！";
    if(!headers_sent()) {
        // redirect
        if(0 === $time) {
            header('Location: ' . $url);
        } else {
            header("refresh:{$time};url={$url}");
            echo($msg);
        }
        exit();
    } else {
        $str = "<meta http-equiv='Refresh' content='{$time};URL={$url}'>";
        if($time != 0)
            $str .= $msg;
        exit($str);
    }
}

/**
 * 导入文件
 * @param string $path
 * @param bool or string $ext
 * @param string $baseUrl
 * @return mixed
 */
function import($path, $ext = true, $baseUrl = COM_DIR) {
    $file = $baseUrl.str_replace('.', '/', $path);
    $file .= (is_bool($ext) ? ($ext ? '.class.php' : '.php') : $ext);
    $file = realpath($file);
    static $f_cache = array();
    $env_name = "IMPORT_{$file}";
    if(!isset($f_cache[$env_name])) {
        if(is_file($file)) {
            $f_cache[$env_name] = require ($file);
        } else {
            return false;
        }
    }
    return $f_cache[$env_name];
}

/**
 * 实例化一个没有模型文件的Model
 * @param string $name Model名称 支持指定基础模型 例如 MongoModel:User
 * @return Model
 */
function M($name='') {
    static $m_cache = array();
    $cacheName = "__{$name}_Model__";
    if(!isset($m_cache[$cacheName])) {
        if(strpos($name, '.') !== false){ // 是否调用其他app下面的模型对象
        
            list($app,$name) = explode('.',$name);
            $appDir = dirname(APP_DIR).__DS__.ucfirst($app).__DS__;
        }else{
            // 解决不同应用调用模型对象出现目录重叠的问题
            $traceArr = debug_backtrace();
            if(isset($traceArr[0]['file']) AND strrpos($file=$traceArr[0]['file'], 'Model.php')){
                $appDir = dirname(APP_DIR).__DS__.basename(dirname(dirname($file))).__DS__;// 取得应用目录名称
            } else {
                $appDir = APP_DIR;
            }
        }
        $modelName = ucfirst($name) . 'Model';
        import("Model.{$modelName}", false, $appDir);//尝试导入应用Model文件夹中的class类文件
        if(!class_exists($modelName, true)){
            //echo '<pre>';print_r(debug_backtrace());
            E('模型不存在: '.$modelName);
        }
        $modelObj = new $modelName();
        $m_cache[$cacheName] = $modelObj;
    }
    return $m_cache[$cacheName];
}

/**
 * 实例化一个DB模型
 * @param string $name Model名称 支持指定基础模型 例如 MongoModel:User
 * @param string $tablePrefix 表前缀
 * @param mixed $connection 数据库连接信息
 * @return Model
 */
function DB($name='', $tablePrefix='', $connection='') {
    static $_db_model = array();
    if(strpos($name,':')) {
        list($class,$name) = explode(':',$name);
    }else{
        $class = 'Model';//huanran.zhao
    }
    $guid = (is_array($connection)?implode('',$connection):$connection).$tablePrefix . $name . '_' . $class;
    if (!isset($_db_model[$guid]))
        $_db_model[$guid] = new $class($name,$tablePrefix,$connection);
    return $_db_model[$guid];
}

/**
 * 获取配置文件
 * @param string $file_name
 * @return mixed
 */
function config($file_name) {
    static $fileData  = array();
    if(!isset($fileData[$file_name])) {
        $file = realpath(APP_DIR.'Config/' . $file_name . '.inc.php');
        if(is_file($file)) {
            $fileData[$file_name] = require ($file);
        } else {
            return false;
        }
    }
    return $fileData[$file_name];
}


/**
 * 文件数据读写(简单数据类型、数组、字符串等)
 * @param string $name
 * @param string $value
 * @param string $path
 */
function F($name, $value='', $path=DATA_DIR) {
    static $f_cache = array();
    $fileName = $path.$name.'.php';
    if($value !== '') {
        if(is_null($value)) return File::del($fileName); // 如果传递的值置为null，将删除文件缓存。
        $dir = dirname($fileName);
        if(!is_dir($dir)) mk_dir($dir);
        return File::write($fileName, "<?php\nreturn ".var_export($value,true).";\n?>", File::WRITE);
    } elseif(isset($f_cache[$name])) {
        $value = $f_cache[$name];
    } elseif(is_file($fileName)) {
        $value = include $fileName;
        $f_cache[$name] = $value;
    } else {
        $value = false;
    }
    return $value;
}

/**
 * 获取客户端IP地址
 * @param integer $type 返回类型 0 返回IP地址 1 返回IPV4地址数字
 * @param boolean $adv 是否进行高级模式获取（有可能被伪装） 
 * @return mixed
 */
function get_client_ip($type = 0,$adv=true) {
    $type       =  $type ? 1 : 0;
    static $ip  =   NULL;
    if ($ip !== NULL) return $ip[$type];
    if($adv){
        if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
            $arr    =   explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
            $pos    =   array_search('unknown',$arr);
            if(false !== $pos) unset($arr[$pos]);
            $ip     =   trim($arr[0]);
        }elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
            $ip     =   $_SERVER['HTTP_CLIENT_IP'];
        }elseif (isset($_SERVER['REMOTE_ADDR'])) {
            $ip     =   $_SERVER['REMOTE_ADDR'];
        }
    }elseif (isset($_SERVER['REMOTE_ADDR'])) {
        $ip     =   $_SERVER['REMOTE_ADDR'];
    }
    // IP地址合法验证
    $long = sprintf("%u",ip2long($ip));
    $ip   = $long ? array($ip, $long) : array('0.0.0.0', 0);
    return $ip[$type];
}

/**
 * 抛出异常处理
 * @param string $msg 异常消息
 * @param integer $code 异常代码 默认为0
 * @return void
 */
function E($msg, $code=0) {
    throw new Exception($msg, $code);
}

/**
 * 添加和获取页面Trace记录
 * @param string $value 变量
 * @param string $label 标签
 * @param string $level 日志级别
 * @param boolean $record 是否记录日志
 * @return void
 */
function trace($value='[dream]',$label='',$level='DEBUG',$record=false) {
    return class_exists('My') ? My::trace($value,$label,$level,$record) : '';    
}

/**
 * 输出信息，程序终止退出
 * @return void
 */
function halt($data, $attach=null) {
    //清楚输出缓存中的内容
    ob_end_clean();
    if(class_exists('My') and My::is_ajax()) { //ajax提交
        $data = (is_array($data)) ? implode('<br/>', $data) : $data;
        $output = json_encode(array('statusCode'=>300, 'message'=>$data, 'attach'=>$attach));
    } else {
        //错误信息以执行过的函数堆栈信息显示 back trace funcation
        Log::showDebugBackTrace($data);
    }
    exit($output);
}

/**
 * 循环创建目录
 * @param string $dir
 * @param string $mode
 */
function mk_dir($dir, $mode = 0777) {
    if(empty($dir)) return false;
    if (is_dir($dir)) return true;
    if (!@mk_dir(dirname($dir),$mode)) return false;
    return @mkdir($dir,$mode);
}

/**
 * 递归删除目录
 * @param string $dir
 * @return void
 */
function rm_dir($dir){
    if(is_dir($dir)) {
        $objects = scandir($dir);
        foreach($objects as $object) {
            if($object != '.' && $object != '..') {
                $file = $dir.'/'.$object;
                if (filetype($file) == 'dir')
                    rm_dir($file);
                else
                    unlink($file);
            }
        }
        reset($objects);
        rmdir($dir);
    }
}

/**
 * 支持按字段对数组进行排序
 * @param array $list 要排序的数组
 * @param string $field 排序的字段名
 * @param array $sortby 排序类型  asc正向排序 desc逆向排序 nat自然排序
 * @return array
 */
function list_sort_by($list,$field, $sortby='asc') {
    if(is_array($list)) {
        $refer = $resultSet = array();
        foreach ($list as $i => $data) $refer[$i] = &$data[$field];
        switch ($sortby) {
            case 'asc': // 正向排序
                asort($refer);
                break;
            case 'desc':// 逆向排序
                arsort($refer);
                break;
            case 'nat': // 自然排序
                natcasesort($refer);
                break;
        }
        foreach ( $refer as $key=> $val) $resultSet[] = &$list[$key];
        return $resultSet;
    }
    return false;
}

/**
 * 把返回的数据集转换成Tree
 * @param array $list 要转换的数据集
 * @param string $pid parent标记字段
 * @param string $level level标记字段
 * @return array
 */
function list_to_tree($list, $pk='id',$pid = 'pid',$child = '_child',$root=0) {
    //创建Tree
    $tree = array();
    if(is_array($list)) {
        //创建基于主键的数组引用
        $refer = array();
        foreach ($list as $key => $data) {
            $refer[$data[$pk]] =& $list[$key];
        }
        foreach ($list as $key => $data) {
            // 判断是否存在parent
            $parentId = $data[$pid];
            if ($root == $parentId) {
                $tree[] =& $list[$key];
            } else {
                if (isset($refer[$parentId])) {
                    $parent =& $refer[$parentId];
                    $parent[$child][] =& $list[$key];
                }
            }
        }
    }
    return $tree;
}

/**
 * 获取和设置配置参数 支持批量定义
 * @param string|array $name 配置变量
 * @param mixed $value 配置值
 * @param mixed $default 默认值
 * @return mixed
 */
function C($name=null, $value=null,$default=null) {
    //获取Config文章（包含|字符）
    if(is_string($name) AND strpos($name,"|")!==false){
        $name = explode('|', $name);
        return My::alias2field('config', $name[0], 'params.'.$name[1]);
    }
    static $_config = array();
    // 无参数时获取所有
    if (empty($name)) {
        return $_config;
    }
    // 优先执行设置获取或赋值
    if (is_string($name)) {
        if (!strpos($name, '.')) {
            $name = strtoupper($name);
            if (is_null($value))
                return isset($_config[$name]) ? $_config[$name] : $default;
            $_config[$name] = $value;
            return null;
        }
        // 二维数组设置和获取支持
        $name = explode('.', $name);
        $name[0]   =  strtoupper($name[0]);
        if (is_null($value))
            return isset($_config[$name[0]][$name[1]]) ? $_config[$name[0]][$name[1]] : $default;
        $_config[$name[0]][$name[1]] = $value;
        return null;
    }
    // 批量设置
    if (is_array($name)){
        $_config = array_merge($_config, array_change_key_case($name,CASE_UPPER));
        return null;
    }
    return null; // 避免非法参数
}

/**
 * 执行系统命令
 * @param string $commond
 * @return string
 */
function execute($commond) {
    $result = null;
    if ($commond) {
        if(function_exists('system')) {
            @ob_start();
            @system($commond);
            $result = @ob_get_contents();
            @ob_end_clean();
        } elseif(function_exists('passthru')) {
            @ob_start();
            @passthru($commond);
            $result = @ob_get_contents();
            @ob_end_clean();
        } elseif(function_exists('shell_exec')) {
            $result = @shell_exec($commond);
        } elseif(function_exists('exec')) {
            @exec($commond, $result);
            $result = join("\n", $result);
        } elseif(@is_resource($fop = @popen($commond, "r"))) {
            while(!@feof($fop)) {
                $result .= @fread($fop, 1024);
            }
            @pclose($fop);
        }
    }
    return $result;
}

/**
 * 获取和设置语言定义(不区分大小写)
 * @param string|array $name 语言变量
 * @param mixed $value 语言值或者变量
 * @return mixed
 */
function L($name=null, $value=null) {
    static $_lang = array();
    // 空参数返回所有定义
    if (empty($name))
        return $_lang;
    // 判断语言获取(或设置)
    // 若不存在,直接返回全大写$name
    if (is_string($name)) {
        $name   =   strtoupper($name);
        if (is_null($value)){
            return isset($_lang[$name]) ? $_lang[$name] : $name;
        }elseif(is_array($value)){
            // 支持变量
            $replace = array_keys($value);
            foreach($replace as &$v){
                $v = '{$'.$v.'}';
            }
            return str_replace($replace,$value,isset($_lang[$name]) ? $_lang[$name] : $name);        
        }
        $_lang[$name] = $value; // 语言定义
        return;
    }
    // 批量定义
    if (is_array($name))
        $_lang = array_merge($_lang, array_change_key_case($name, CASE_UPPER));
    return;
}

/**
 * 获取输入参数 支持过滤和默认值
 * 使用方法:
 * <code>
 * I('id',0); 获取id参数 自动判断get或者post
 * I('post.name','','htmlspecialchars'); 获取$_POST['name']
 * I('get.'); 获取$_GET
 * </code>
 * @param string $name 变量的名称 支持指定类型
 * @param mixed $default 不存在的时候默认值
 * @param mixed $filter 参数过滤方法
 * @param mixed $datas 要获取的额外数据源
 * @return mixed
 */
function I($name,$default='',$filter=null,$datas=null) {
    if(strpos($name,'/')){ // 指定修饰符
        list($name,$type)   =   explode('/',$name,2);
    }
    if(strpos($name,'.')) { // 指定参数来源
        list($method,$name) =   explode('.',$name,2);
    }else{ // 默认为自动判断
        $method =   'param';
    }
    switch(strtolower($method)) {
        case 'get'     :   $input =& $_GET;break;
        case 'post'    :   $input =& $_POST;break;
        case 'put'     :   parse_str(file_get_contents('php://input'), $input);break;
        case 'param'   :
            switch($_SERVER['REQUEST_METHOD']) {
                case 'POST':
                    $input  =  $_POST;
                    break;
                case 'PUT':
                    parse_str(file_get_contents('php://input'), $input);
                    break;
                default:
                    $input  =  $_GET;
            }
            break;
        case 'path'    :   
            $input  =   array();
            if(!empty($_SERVER['PATH_INFO'])){
                $depr   =   C('URL_PATHINFO_DEPR');
                $input  =   explode($depr,trim($_SERVER['PATH_INFO'],$depr));            
            }
            break;
        case 'request' :   $input =& $_REQUEST;   break;
        case 'session' :   $input =& $_SESSION;   break;
        case 'cookie'  :   $input =& $_COOKIE;    break;
        case 'server'  :   $input =& $_SERVER;    break;
        case 'globals' :   $input =& $GLOBALS;    break;
        case 'data'    :   $input =& $datas;      break;
        default:
            return NULL;
    }
    if(''==$name) { // 获取全部变量
        $data       =   $input;
        $filters    =   isset($filter)?$filter:C('DEFAULT_FILTER');
        if($filters) {
            if(is_string($filters)){
                $filters    =   explode(',',$filters);
            }
            foreach($filters as $filter){
                $data   =   array_map_recursive($filter,$data); // 参数过滤
            }
        }
    }elseif(isset($input[$name])) { // 取值操作
        $data       =   $input[$name];
        $filters    =   isset($filter)?$filter:C('DEFAULT_FILTER');
        if($filters) {
            if(is_string($filters)){
                $filters    =   explode(',',$filters);
            }elseif(is_int($filters)){
                $filters    =   array($filters);
            }
            
            foreach($filters as $filter){
                if(function_exists($filter)) {
                    $data   =   is_array($data) ? array_map_recursive($filter,$data) : $filter($data); // 参数过滤
                }elseif(0===strpos($filter,'/')){
                    // 支持正则验证
                    if(1 !== preg_match($filter,(string)$data)){
                        return   isset($default) ? $default : NULL;
                    }
                }else{
                    $data   =   filter_var($data,is_int($filter) ? $filter : filter_id($filter));
                    if(false === $data) {
                        return   isset($default) ? $default : NULL;
                    }
                }
            }
        }
        if(!empty($type)){
            switch(strtolower($type)){
                case 's':   // 字符串
                    $data   =   (string)$data;
                    break;
                case 'a':   // 数组
                    $data   =   (array)$data;
                    break;
                case 'd':   // 数字
                    $data   =   (int)$data;
                    break;
                case 'f':   // 浮点
                    $data   =   (float)$data;
                    break;
                case 'b':   // 布尔
                    $data   =   (boolean)$data;
                    break;
            }
        }
    }else{ // 变量默认值
        $data       =    isset($default)?$default:NULL;
    }
    is_array($data) && array_walk_recursive($data,'think_filter');
    return $data;
}
function array_map_recursive($filter, $data) {
     $result = array();
     foreach ($data as $key => $val) {
         $result[$key] = is_array($val)
             ? array_map_recursive($filter, $val)
             : call_user_func($filter, $val);
     }
     return $result;
}
function think_filter(&$value){
    // TODO 其他安全过滤
    // 过滤查询特殊字符
    if(preg_match('/^(EXP|NEQ|GT|EGT|LT|ELT|OR|XOR|LIKE|NOTLIKE|NOT BETWEEN|NOTBETWEEN|BETWEEN|NOTIN|NOT IN|IN)$/i',$value)){
        $value .= ' ';
    }
}

// 自动表单令牌验证
// TODO  ajax无刷新多次提交暂不能满足
function token($data='') {
    // 支持使用token(false) 关闭令牌验证
    //if(isset($this->options['token']) && !$this->options['token']) return true;
    if(TOKEN_ON==true){
        $name   = 'token';
        if(empty($data) AND isset($_POST))
            $data = $_POST;
        if(empty($data[$name]) || !isset($_SESSION[$name])) { // 令牌数据无效
            return false;
        }
        // 令牌验证
        list($key,$value)  =  explode('_',$data[$name]);
        if($value && isset($_SESSION[$name][$key]) && $_SESSION[$name][$key] === $value) { // 防止重复提交
            //unset($_SESSION[$name][$key]); //验证完成销毁session  由于本系统是ajax提交的表单,故将unset操作放到$this->ajaxReturn(200)操作时完成
            $_SESSION['token_key'] = $key;//记录一下,方便在common中删除该key的token
            return true;
        }
        // 开启TOKEN重置
        if(C('TOKEN_RESET')) unset($_SESSION[$name][$key]);
        return false;
    }
    return true;
}

/**
 * session管理函数
 * @param string|array $name session名称 如果为数组则表示进行session设置
 * @param mixed $value session值
 * @return mixed
 */
function session($name='',$value='') {
    $prefix   =  C('SESSION_PREFIX');
    if(is_array($name)) { // session初始化 在session_start 之前调用
        if(isset($name['prefix'])) C('SESSION_PREFIX',$name['prefix']);
        if(C('VAR_SESSION_ID') && isset($_REQUEST[C('VAR_SESSION_ID')])){
            session_id($_REQUEST[C('VAR_SESSION_ID')]);
        }elseif(isset($name['id'])) {
            session_id($name['id']);
        }
        if('common' != APP_MODE){ // 其它模式可能不支持
            ini_set('session.auto_start', 0);
        }
        if(isset($name['name']))            session_name($name['name']);
        if(isset($name['path']))            session_save_path($name['path']);
        if(isset($name['domain']))          ini_set('session.cookie_domain', $name['domain']);
        if(isset($name['expire']))          ini_set('session.gc_maxlifetime', $name['expire']);
        if(isset($name['use_trans_sid']))   ini_set('session.use_trans_sid', $name['use_trans_sid']?1:0);
        if(isset($name['use_cookies']))     ini_set('session.use_cookies', $name['use_cookies']?1:0);
        if(isset($name['cache_limiter']))   session_cache_limiter($name['cache_limiter']);
        if(isset($name['cache_expire']))    session_cache_expire($name['cache_expire']);
        if(isset($name['type']))            C('SESSION_TYPE',$name['type']);
        if(C('SESSION_TYPE')) { // 读取session驱动
            $type   =   C('SESSION_TYPE');
            $class  =   strpos($type,'\\')? $type : 'Think\\Session\\Driver\\'. ucwords(strtolower($type));
            $hander =   new $class();
            session_set_save_handler(
                array(&$hander,"open"), 
                array(&$hander,"close"), 
                array(&$hander,"read"), 
                array(&$hander,"write"), 
                array(&$hander,"destroy"), 
                array(&$hander,"gc")); 
        }
        // 启动session
        if(C('SESSION_AUTO_START'))  session_start();
    }elseif('' === $value){ 
        if(''===$name){
            // 获取全部的session
            return $prefix ? $_SESSION[$prefix] : $_SESSION;
        }elseif(0===strpos($name,'[')) { // session 操作
            if('[pause]'==$name){ // 暂停session
                session_write_close();
            }elseif('[start]'==$name){ // 启动session
                session_start();
            }elseif('[destroy]'==$name){ // 销毁session
                $_SESSION =  array();
                session_unset();
                session_destroy();
            }elseif('[regenerate]'==$name){ // 重新生成id
                session_regenerate_id();
            }
        }elseif(0===strpos($name,'?')){ // 检查session
            $name   =  substr($name,1);
            if(strpos($name,'.')){ // 支持数组
                list($name1,$name2) =   explode('.',$name);
                return $prefix?isset($_SESSION[$prefix][$name1][$name2]):isset($_SESSION[$name1][$name2]);
            }else{
                return $prefix?isset($_SESSION[$prefix][$name]):isset($_SESSION[$name]);
            }
        }elseif(is_null($name)){ // 清空session
            if($prefix) {
                unset($_SESSION[$prefix]);
            }else{
                $_SESSION = array();
            }
        }elseif($prefix){ // 获取session
            if(strpos($name,'.')){
                list($name1,$name2) =   explode('.',$name);
                return isset($_SESSION[$prefix][$name1][$name2])?$_SESSION[$prefix][$name1][$name2]:null;  
            }else{
                return isset($_SESSION[$prefix][$name])?$_SESSION[$prefix][$name]:null;                
            }            
        }else{
            if(strpos($name,'.')){
                list($name1,$name2) =   explode('.',$name);
                return isset($_SESSION[$name1][$name2])?$_SESSION[$name1][$name2]:null;  
            }else{
                return isset($_SESSION[$name])?$_SESSION[$name]:null;
            }            
        }
    }elseif(is_null($value)){ // 删除session
        if(strpos($name,'.')){
            list($name1,$name2) =   explode('.',$name);
            if($prefix){
                unset($_SESSION[$prefix][$name1][$name2]);
            }else{
                unset($_SESSION[$name1][$name2]);
            }
        }else{
            if($prefix){
                unset($_SESSION[$prefix][$name]);
            }else{
                unset($_SESSION[$name]);
            }
        }
    }else{ // 设置session
        if($prefix){
            if (!isset($_SESSION[$prefix])) {
                $_SESSION[$prefix] = array();
            }
            $_SESSION[$prefix][$name]   =  $value;
        }else{
            $_SESSION[$name]  =  $value;
        }
    }
    return null;
}

/**
 * 根据PHP各种类型变量生成唯一标识号
 * @param mixed $mix 变量
 * @return string
 */
function to_guid_string($mix) {
    if (is_object($mix)) {
        return spl_object_hash($mix);
    } elseif (is_resource($mix)) {
        $mix = get_resource_type($mix) . strval($mix);
    } else {
        $mix = serialize($mix);
    }
    return md5($mix);
}

/**
 * 设置和获取统计数据
 * 使用方法:
 * <code>
 * N('db',1); // 记录数据库操作次数
 * N('read',1); // 记录读取次数
 * echo N('db'); // 获取当前页面数据库的所有操作次数
 * echo N('read'); // 获取当前页面读取次数
 * </code>
 * @param string $key 标识位置
 * @param integer $step 步进值
 * @return mixed
 */
function N($key, $step=0,$save=false) {
    static $_num    = array();
    if (!isset($_num[$key])) {
        $_num[$key] = (false !== $save)? S('N_'.$key) :  0;
    }
    if (empty($step))
        return $_num[$key];
    else
        $_num[$key] = $_num[$key] + (int) $step;
    if(false !== $save){ // 保存结果
        S('N_'.$key,$_num[$key],$save);
    }
}

/**
 * 记录和统计时间(秒)和内存使用情况
 * 使用方法:
 * <code>
 *   T('begin'); // 记录开始标记位
 *   // ... 区间运行代码
 *   T('end'); // 记录结束标签位
 *   echo T('begin','end').' S';//输出区间运行时间(单位秒) //精确到小数后6位:echo T('begin','end',6);
 *   echo T('begin','end','m').'kb'; //统计区间内存使用情况(单位kb) //其中统计内存使用需要 MEMORY_LIMIT_ON 常量为true才有效
 * </code>
 * @param string $start 开始标签
 * @param string $end 结束标签
 * @param integer|string $dec 小数位或者m
 * @return mixed
 */
function T($start,$end='',$dec=3) {
    static $_info       =   array();
    static $_mem        =   array();
    if(is_float($end)) { // 记录时间
        $_info[$start]  =   $end;
    }elseif(!empty($end)){ // 统计时间和内存使用
        if(!isset($_info[$end])) $_info[$end]       =  microtime(TRUE);
        if(MEMORY_LIMIT_ON && $dec=='m'){
            if(!isset($_mem[$end])) $_mem[$end]     =  memory_get_usage();
            return number_format(($_mem[$end]-$_mem[$start])/1024);
        }else{
            return number_format(($_info[$end]-$_info[$start]),$dec);
        }
    }else{ // 记录时间和内存使用
        $_info[$start]  =  microtime(TRUE);
        if(MEMORY_LIMIT_ON) $_mem[$start]           =  memory_get_usage();
    }
}

/**
 * 缓存管理
 * @param mixed $name 缓存名称，如果为数组表示进行缓存设置
 * @param mixed $value 缓存值
 * @param mixed $options 缓存参数
 * @return mixed
 */
function S($name, $value='', $options=null) {
    static $cache   =   '';
    // 缓存操作的同时初始化
    if(is_array($options)){
        $type       =   isset($options['type'])?$options['type']:'';
        $cache      =   Cache::getInstance($type,$options);
    }
    // 缓存初始化
    elseif(is_array($name)) {
        $type       =   isset($name['type'])?$name['type']:'';
        $cache      =   Cache::getInstance($type,$name);
        return $cache;
    }
    // 自动初始化
    elseif(empty($cache)) {
        $cache      =   Cache::getInstance();
    }

    //获取缓存
    if(''===$value OR (is_array($value) AND isset($value['pre']))){ //huanran.zhao 新增：OR (is_array($value) AND isset($value['pre']))
        return $cache->get($name, $value);//huanran.zhao //新增$value参数，主要用于pre参数的传递
    }
    //删除缓存
    elseif(is_null($value)) {
        return $cache->rm($name);
    }
    //添加缓存
    else {
        if(is_array($options)) {
            $expire     =   isset($options['expire'])?$options['expire']:NULL;
        }else{
            $expire     =   is_numeric($options)?$options:NULL;
        }
        return $cache->set($name, $value, $expire, $options);//huanran.zhao //添加$options参数，主要用于pre参数的传递
    }
}

/**
 * 字符串命名风格转换
 * type 0 将Java风格转换为C的风格 1 将C风格转换为Java的风格
 * @param string $name 字符串
 * @param integer $type 转换类型
 * @return string
 */
function parse_name($name, $type=0) {
    if($type) {
        if(!function_exists('_temp_')){ function _temp_($match){return strtoupper($match[1]);} }
        return ucfirst(preg_replace_callback('/_([a-zA-Z])/', '_temp_', $name));
    } else {
        return strtolower(trim(preg_replace("/[A-Z]/", "_\\0", $name), "_"));
    }
}

/**
 * 发送HTTP状态
 * @param integer $code 状态码
 * @return void
 */
function send_http_status($code) {
    static $_status = array(
        // Success 2xx
        200 => 'OK',
        // Redirection 3xx
        301 => 'Moved Permanently',
        302 => 'Moved Temporarily ',  // 1.1
        // Client Error 4xx
        400 => 'Bad Request',
        403 => 'Forbidden',
        404 => 'Not Found',
        // Server Error 5xx
        500 => 'Internal Server Error',
        503 => 'Service Unavailable',
    );
    if(isset($_status[$code])) {
        header('HTTP/1.1 '.$code.' '.$_status[$code]);
        // 确保FastCGI模式下正常
        header('Status:'.$code.' '.$_status[$code]);
    }
}

//自定义函数，让I函数可以处理单引号
function htmlspecialchars_plus($str){
    return htmlspecialchars($str,ENT_QUOTES);
}